"""
shelveshelve模块与pickle模块的功能相近,比pickle用起来更为简单,
shelve类似于一个key-value数据库，可以很方便的用来保存Python的内存对象，
其内部使用pickle来序列化数据，简单来说，使用者可以将一个列表、字典、
或者用户自定义的类实例保存到shelve中，下次需要用的时候直接取出来，
就是一个Python内存对象，不需要像传统数据库一样，先取出数据，
然后用这些数据重新构造一遍所需要的对象。
"""
from xjlibrary.our_file_dir import BaseDir

curpath = BaseDir.get_file_dir_absolute(__file__)
TopPath = BaseDir.get_upper_dir(curpath, -2)
dirPath = BaseDir.get_new_path(TopPath, "dbdata", "shelve")
BaseDir.create_dir(dirPath)

import shelve


class Mshelve(object):
    def __init__(self):
        self.dbfile = BaseDir.get_new_path(dirPath, "all.db")

    def set_dbfile(self, dbfile):
        self.dbfile = dbfile

    def open_shelve(self, flag="c", protocol=2, writeback=False):
        # open 返回一个Shelf类的实例
        #
        # 参数flag的取值范围：
        # 'r'：只读打开
        # 'w'：读写访问
        # 'c'：读写访问，如果不存在则创建
        # 'n'：读写访问，总是创建新的、空的数据库文件
        #
        # protocol：与pickle库一致
        # writeback：为True时，当数据发生变化会回写，不过会导致内存开销比较大
        self.d = shelve.open(self.dbfile, flag='c', protocol=2, writeback=False)
        assert isinstance(self.d, shelve.Shelf)

    def inertdb(self, key, value):
        """
        # writeback是False，因此对value进行修改是不起作用的
         # 在数据库中插入一条记录
          d['abc'] = {'name': ['a', 'b']}
          d.sync()

          print d['abc']

          # writeback是False，因此对value进行修改是不起作用的
          d['abc']['x'] = 'x'
          print d['abc'] # 还是打印 {'name': ['a', 'b']}

          # 当然，直接替换key的value还是起作用的
          d['abc'] = 'xxx'
          print d['abc']

        :param key:
        :param value:
        :return:
        """
        self.d[key] = value
        self.d.sync()

    def close(self):
        """
        close时会提交更改
        :return:
        """
        self.d.close()

"""
这个有一个潜在的小问题，如下：

>>> import shelve 
>>> s = shelve.open('test.dat') 
>>> s['x'] = ['a', 'b', 'c'] 
>>> s['x'].append('d') 
>>> s['x'] 
['a', 'b', 'c'] 

存储的d到哪里去了呢？其实很简单，d没有写回，你把['a', 'b', 'c']存到了x，当你再次读取s['x']的时候，s['x']只是一个拷贝，而你没有将拷贝写回，所以当你再次读取s['x']的时候，它又从源中读取了一个拷贝，所以，你新修改的内容并不会出现在拷贝中，解决的办法就是，第一个是利用一个缓存的变量，如下所示
>>> temp = s['x'] 
>>> temp.append('d') 
>>> s['x'] = temp 
>>> s['x'] 
['a', 'b', 'c', 'd']
"""

